package com.tunan.system.web;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.swing.text.html.Option;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import redis.clients.jedis.exceptions.JedisException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tunan.common.Result;
import com.tunan.common.resultSub.ResultFailure;
import com.tunan.common.resultSub.ResultToken;
import com.tunan.persistence.model.LsjToken;
import com.tunan.persistence.model.SystemMenuExt;
import com.tunan.persistence.model.TSysMenu;
import com.tunan.persistence.model.TSysMenuLink;
import com.tunan.persistence.model.TSysRoleLink;
import com.tunan.persistence.model.TSysUser;
import com.tunan.persistence.model.TSysUserLoginTn;
import com.tunan.system.service.SysMenuLinkService;
import com.tunan.system.service.SysMenuService;
import com.tunan.system.service.SysRoleLinkService;
import com.tunan.system.service.SysUserLoginService;
import com.tunan.system.service.SysUserService;
import com.tunan.system.service.TokenService;
import com.tunan.utils.RedisUtils;

@RestController()
@RequestMapping("/loginController")
public class LoginController {

	@Autowired
	private RedisUtils redisUtils;

	@Autowired
	private SysUserLoginService sysUserLoginService;

	@Autowired
	private SysUserService sysUserService;

	@Autowired
	private TokenService tokenSerivce;

	@Autowired
	private SysRoleLinkService sysRoleLinkService;

	@Autowired
	private SysMenuLinkService sysMenuLinkService;

	@Autowired
	private SysMenuService sysMenuService;

	private Logger log = Logger.getLogger(LoginController.class);

	public static String[] LOGIN_VD = { "corpCk" };

	private ObjectMapper objectMapper = new ObjectMapper();

	/**
	 * 
	 * @param tSysUser
	 * @return Result
	 * @Description 登录
	 * @date 2016年3月30日
	 * @author kinda
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public Result login(TSysUser tSysUser, HttpServletRequest request) {
		TSysUser targetUser = sysUserService.findByDlm(tSysUser);
		Optional<String> userStr = Optional.empty();
		try {
			userStr = Optional.ofNullable(objectMapper.writeValueAsString(targetUser));
		} catch (JsonProcessingException e1) {
			userStr = Optional.ofNullable(targetUser.getDlm());
		}
		
		
		/*
		 * Map map = new HashMap(); map.put("xzq", "88311"); map.put("dwmc",
		 * "东大软件");
		 */

		// Result testr = ValidateBridge.validate(LOGIN_VD, map, null, null);
		// String s = ((IKeyGenerator)
		// SpringContextUtil.getBean("ywlshKeyGen")).createKey(tSysUser, map);
		// System.out.println(s);
		// System.out.println(testr.getMessage());
		if (targetUser != null) {
			TSysUserLoginTn userLogin = sysUserLoginService.findByDlm(targetUser.getDlm());

			ResultToken resultToken = new ResultToken();
			TSysUserLoginTn ul = new TSysUserLoginTn();
			ul.setContent(userStr.orElse(targetUser.getDlm()));
			System.out.println(userStr.get());
			System.out.println(ul.getContent());

			Calendar calendar = Calendar.getInstance();
			calendar.add(Calendar.HOUR, 8);
			Calendar deadline = Calendar.getInstance();

			try {
				// getMenu(targetUser,request);
				if (userLogin != null) {
					deadline.setTime(userLogin.getDeadline());
					if (tokenSerivce.checkToken(userLogin.getAccessToken() + "_")) {
						LsjToken token = new LsjToken();
						token.setAccessToken(userLogin.getAccessToken());
						resultToken.setToken(token);
					} else {
						resultToken.setToken(tokenSerivce.reprocessToken(userLogin.getAccessToken(),
								userStr.orElse(targetUser.getDlm())));
						if (calendar.after(deadline)) {
							new Thread(() -> {
								updateDeadline(targetUser, ul, calendar);
							}).start();
						}
					}
				} else {
					resultToken.setToken(tokenSerivce.createToken(userStr.orElse(targetUser.getDlm())));
					if (resultToken.getToken() != null) {
						new Thread(() -> {
							createUserLogin(targetUser, resultToken, ul, calendar);
						}).start();
					} else {
						redisUtils.setRedisLived(false);
						return new ResultFailure("系统繁忙");
					}
				}

			} catch (JedisException e) {
				log.error(e.getMessage(), e);
				if (redisUtils.isRedisLived()) {
					redisUtils.setRedisLived(false);
				}
				if (userLogin != null) {
					deadline.setTime(userLogin.getDeadline());
					updateDeadline(targetUser, ul, calendar);
					LsjToken token = new LsjToken();
					token.setAccessToken(userLogin.getAccessToken());
					token.setFreshToken(userLogin.getAccessToken() + "_");
					resultToken.setToken(token);
				} else {
					do {
						String token = tokenSerivce.createAccessToken();
						if (sysUserLoginService.selectByToken(token).isPresent()) {
							continue;
						}
						LsjToken lsjToken = new LsjToken();
						lsjToken.setAccessToken(token);
						resultToken.setToken(lsjToken);
					} while (false);
					createUserLogin(targetUser, resultToken, ul, calendar);
				}

			}
			getMenu(targetUser, request);
			return resultToken;

		} else {
			return new ResultFailure("用户名密码有误");
		}

	}

	private void updateDeadline(TSysUser targetUser, TSysUserLoginTn ul, Calendar calendar) {
		ul.setDlm(targetUser.getDlm());
		ul.setDeadline(calendar.getTime());
		sysUserLoginService.updateDeadline(ul);
	}

	private void createUserLogin(TSysUser targetUser, ResultToken resultToken, TSysUserLoginTn ul, Calendar calendar) {
		ul.setDlm(targetUser.getDlm());
		ul.setDeadline(calendar.getTime());
		ul.setAccessToken(resultToken.getToken().getAccessToken());
		sysUserLoginService.insert(ul);
	}

	/**
	 * 
	 * @return Result
	 * @Description 从拦截器过来，返回json
	 * @date 2016年3月28日
	 * @author kinda
	 */
	@RequestMapping(value = "/staleToken")
	public Result staleToken() {
		return new ResultFailure("Token已过期");
	}

	/**
	 * 
	 * @param request
	 * @param response
	 * @return Result
	 * @Description 更新token
	 * @date 2016年3月30日
	 * @author kinda
	 */
	@RequestMapping(value = "/updateToken", method = RequestMethod.POST)
	@Deprecated
	public Result updateToken(HttpServletRequest request) {

		Optional<String> freshToken = Optional.ofNullable(request.getParameter("freshToken"));
		if (freshToken.isPresent()) {
			if (tokenSerivce.checkToken(freshToken.get())) {
				ResultToken resultToken = new ResultToken();
				resultToken.setToken(tokenSerivce.changToken(freshToken.get()));
				return resultToken;
			}
		}
		return new ResultFailure("令牌已过期，请重新登录");
	}

	/**
	 * 
	 * @return Result
	 * @测试可删除
	 * @date 2016年3月24日
	 * @author kinda
	 */
	@RequestMapping(value = "/test1/{id}", method = RequestMethod.GET)
	public List<TSysUser> test1(@PathVariable(value = "id") Integer id, HttpServletResponse response) {
		return sysUserService.findAll();

	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void getMenu(TSysUser user, HttpServletRequest request) {
		HttpSession session = request.getSession();
		String roles = "";
		List<TSysRoleLink> roleLink;// 人员角色实体的集合
		List<TSysMenuLink> menuLink; // 菜单和角色中间实体
		Set<Object> menuIdList;// 保存所有菜单id值
		Map<String, TSysMenuLink> rightMap;// 保存所有的读写，权限。
		HashMap<String, Object> map = new HashMap<String, Object>();
		try {
			map.clear();
			map.put("czyid", user.getCzyid());
			roleLink = sysRoleLinkService.selectAll(map);// 所有的角色的集合
			menuIdList = new HashSet();
			List<TSysMenuLink> lis = new ArrayList<TSysMenuLink>();
			for (TSysRoleLink relate : roleLink) {
				roles += relate.getRoleid() + ",";
				map.clear();
				map.put("roleId", relate.getRoleid());
				menuLink = sysMenuLinkService.selectAll(map);
				for (TSysMenuLink right : menuLink) {
					lis.add(right);// 保存所有的vo
					menuIdList.add(right.getMenuId());
				}
			}
			rightMap = new HashMap<String, TSysMenuLink>();
			// 对重复的 menuId 权限进行操作
			for (int i = 0; i < lis.size() - 1; i++) {
				for (int j = lis.size() - 1; j > i; j--) {
					if (lis.get(i).getMenuId().equals(lis.get(j).getMenuId())) {

						TSysMenuLink sysI = lis.get(i);
						TSysMenuLink sysJ = lis.get(j);

						TSysMenuLink rig = new TSysMenuLink();
						rig.setMenuId(sysI.getMenuId());

						String define = getInfor(sysI.getDefined(), sysJ.getDefined());
						rig.setDefined(define);

						if ("1".equals(sysI.getW()) || "1".equals(sysJ.getW())) {
							rig.setR("1");
							rig.setW("1");
						} else if (("1".equals(sysI.getR()) || "1".equals(sysJ.getR()))
								&& ("1".equals(sysI.getW()) && "1".equals(sysJ.getW()))) {
							rig.setR("1");
							rig.setW("0");
						} else {
							rig.setR("0");
							rig.setW("0");
						}
						int ii = i;
						lis.remove(i);
						lis.add(ii, rig);
						lis.remove(j);
					}
				}
			}

			// 填充到rightMap 以菜单id为键，TblSystemRoleRight实体为值
			for (TSysMenuLink rig : lis) {
				rightMap.put(rig.getMenuId(), rig);
			}
			// 保存到session
			if (!roles.equals(""))
				roles = roles.substring(0, roles.length() - 1);
			session.setAttribute("roles", roles);
			session.setAttribute("rightMap", rightMap);
			List<SystemMenuExt> list = loadmenuNew(rightMap);
			session.setAttribute("userMenu", list);
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
	}

	// 得到不重复的自定义权限
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private String getInfor(String str, String str2) {
		Set set = new HashSet();
		String s = "";
		if (null != str && !str.equals("")) {
			String[] ary = str.split(",");
			for (int j = 0; j < ary.length; j++) {
				set.add(ary[j]);
			}
		}

		if (null != str2 && !str2.equals("")) {
			String[] ary2 = str2.split(",");
			for (int i = 0; i < ary2.length; i++) {
				set.add(ary2[i]);
			}

		}
		for (Iterator it = set.iterator(); it.hasNext();) {
			s += it.next() + ",";
		}
		return s;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private List<SystemMenuExt> loadmenuNew(Map<String, TSysMenuLink> rightMap) {
		HashMap map = new HashMap();
		map.put("isActive", "1");
		map.put("parentMenu", "0");
		List<TSysMenu> list = null;
		List<SystemMenuExt> listExt = null;
		try {
			list = sysMenuService.selectAll(map);
			listExt = new ArrayList<SystemMenuExt>();
			for (int i = list.size() - 1; i >= 0; i--) {
				TSysMenu sysMenu = list.get(i);
				List<TSysMenu> subListExt = new ArrayList<TSysMenu>();
				map.clear();
				map.put("isActive", "1");
				map.put("parentMenu", sysMenu.getId());
				List<TSysMenu> subList = sysMenuService.selectAll(map);
				if (rightMap.containsKey(sysMenu.getId()) || subList.size() > 0) {
					SystemMenuExt sysMenuExt = new SystemMenuExt();
					boolean b = false;
					for (int j = 0; j < subList.size(); j++) {
						TSysMenu sub = subList.get(j);
						if (rightMap.containsKey(sub.getId())) {
							b = true;
							subListExt.add(sub);
						}
					}
					if (b || rightMap.containsKey(sysMenu.getId())) {
						sysMenuExt.setMenu(sysMenu);
						sysMenuExt.setSubMenus(subListExt);
						listExt.add(sysMenuExt);
					}
				}

			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return listExt;
	}

}
